﻿using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Class1
    {
        [DllImport(@"E:\ex\TestCPPDLL\Debug\TestCPPDLL.dll", EntryPoint = "Add")]
        extern static int Add(int a, int b);

        [DllImport(@"E:\ex\TestCPPDLL\Debug\TestCPPDLL.dll", EntryPoint = "WriteString")]
        extern unsafe static void WriteString(char* c);

        [DllImport(@"E:\ex\TestCPPDLL\Debug\TestCPPDLL.dll", EntryPoint = "AddInt")]
        extern unsafe static void AddInt(int* i);

        [DllImport(@"E:\ex\TestCPPDLL\Debug\TestCPPDLL.dll", EntryPoint = "AddIntArray")]
        extern unsafe static void AddIntArray(int* firstElement, int arraylength);

        [DllImport(@"E:\ex\TestCPPDLL\Debug\TestCPPDLL.dll", EntryPoint = "GetArrayFromCPP")]
        extern unsafe static int* GetArrayFromCPP();


        //定义一个委托，返回值为空，存在一个整型参数
        public delegate void CSCallback(int tick);

        //定义一个用于回调的方法，与前面定义的委托的原型一样
        //该方法会被C++所调用
        static void CSCallbackFunction(int tick)
        {
            Console.WriteLine(tick.ToString());
        }

        //定义一个委托类型的实例，
        //在主程序中该委托实例将指向前面定义的CSCallbackFunction方法
        static CSCallback callback;

        //这里使用CSCallback委托类型来兼容C++里的CPPCallback函数指针
        [DllImport(@"E:\ex\TestCPPDLL\Debug\TestCPPDLL.dll", EntryPoint = "SetCallback")]
        extern static void SetCallback(CSCallback callback);

        [StructLayout(LayoutKind.Sequential)]
        struct Vector3
        {
            public float X, Y, Z;
        }

        [DllImport(@"E:\ex\TestCPPDLL\Debug\TestCPPDLL.dll", EntryPoint = "SendStructFromCSToCPP")]
        extern static void SendStructFromCSToCPP(Vector3 vector);

        static void TEST(string[] args)
        {
            int c = Add(1, 2);
            Console.WriteLine(c);
            //因为使用指针，因为要声明非安全域
            unsafe
            {
                //在传递字符串时，将字符所在的内存固化，
                //并取出字符数组的指针
                fixed (char* p = &("hello".ToCharArray()[0]))
                {
                    //调用方法
                    WriteString(p);
                }
            }

            unsafe
            {
                // 调用C++中的AddInt方法
                int i = 10;

                AddInt(&i);
                Console.WriteLine(i);

                //调用C++中的AddIntArray方法将C#中的数据传递到C++中，并在C++中输出
                int[] CSArray = new int[10];
                for (int iArr = 0; iArr < 10; iArr++)
                {
                    CSArray[iArr] = iArr;
                }

                fixed (int* pCSArray = &CSArray[0])
                {
                    AddIntArray(pCSArray, 10);
                }

                //调用C++中的GetArrayFromCPP方法获取一个C++中建立的数组
                int* pArrayPointer = null;
                pArrayPointer = GetArrayFromCPP();
                for (int iArr = 0; iArr < 10; iArr++)
                {
                    Console.WriteLine(*pArrayPointer);
                    pArrayPointer++;
                }
            }

            //让委托指向将被回调的方法
            callback = CSCallbackFunction;
            //将委托传递给C++
            SetCallback(callback);

            //建立一个Vector3的实例
            Vector3 vector = new Vector3() { X = 10, Y = 20, Z = 30 };
            //将vector传递给C++并在C++中输出
            SendStructFromCSToCPP(vector);

            Console.Read();
        }
    }
}